package com.yykj.hospital.server.service.impl;

import cn.afterturn.easypoi.excel.entity.result.ExcelImportResult;
import com.google.gson.Gson;
import com.yykj.base.client.dto.WordBriefInfo;
import com.yykj.base.client.feign.BaseFeignClient;
import com.yykj.common.constant.CommonConstant;
import com.yykj.common.enums.BanCiType;
import com.yykj.common.enums.ResultEnums;
import com.yykj.common.exception.NormalException;
import com.yykj.common.service.RedisService;
import com.yykj.common.util.*;
import com.yykj.common.vo.PageData;
import com.yykj.hospital.client.dto.*;
import com.yykj.hospital.server.converter.DoctorDTOConverter;
import com.yykj.hospital.server.converter.HotDoctorDTOConverter;
import com.yykj.hospital.server.dto.*;
import com.yykj.hospital.server.form.*;
import com.yykj.hospital.server.model.entity.Hospital;
import com.yykj.hospital.server.model.entity.HospitalDoctor;
import com.yykj.hospital.server.model.entity.HospitalDoctorBindLabel;
import com.yykj.hospital.server.model.entity.banci.HospitalDoctorBanCi;
import com.yykj.hospital.server.model.repository.HospitalDoctorBindLabelRepository;
import com.yykj.hospital.server.model.repository.HospitalDoctorRepository;
import com.yykj.hospital.server.model.repository.HospitalRepository;
import com.yykj.hospital.server.service.DepartmentService;
import com.yykj.hospital.server.service.HospitalDoctorService;
import com.yykj.hospital.server.service.HospitalSettingService;
import com.yykj.hospital.server.service.banci.BanCiSearchService;
import com.yykj.hospital.server.service.qrcode.QrcodeService;
import com.yykj.message.center.client.dto.TDMQMessage;
import com.yykj.message.center.client.enums.MessageType;
import com.yykj.tencent.im.client.feign.TencentImFeignClient;
import com.yykj.tencent.im.client.form.UserProfileForm;
import com.yykj.user.center.client.dto.DoctorConsultationCountDto;
import com.yykj.user.center.client.feign.UserFeignClient;
import com.yykj.user.center.client.form.AddGroupForm;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import javax.persistence.criteria.CriteriaBuilder;
import javax.persistence.criteria.CriteriaQuery;
import javax.persistence.criteria.Predicate;
import javax.persistence.criteria.Root;
import java.time.LocalDateTime;
import java.util.*;

@Slf4j
@Service
public class HospitalDoctorServiceImpl implements HospitalDoctorService {
    @Override
    public HotDoctorDTO editHotDoctor(HospitalHotDoctorEditForm form) {

        HospitalDoctor hospitalDoctor = findById(form.getDoctorId());
        hospitalDoctor.setSorting(form.getSorting());
        hospitalDoctor.setHotStatus(Boolean.TRUE);
        hospitalDoctor = doctorRepository.save(hospitalDoctor);
        return HotDoctorDTOConverter.convert(hospitalDoctor);
    }

    @Override
    public void deleteHotDoctor(String doctorId) {
        HospitalDoctor hospitalDoctor = findById(doctorId);
        hospitalDoctor.setHotStatus(false);
        doctorRepository.save(hospitalDoctor);
    }

    @Override
    public List<HotDoctorDTO> listHotDoctor(Integer hospitalId) {
        List<HospitalDoctor> list = doctorRepository.findAllByHospitalIdAndHotStatusAndNeedShowOrderBySorting(hospitalId, Boolean.TRUE, Boolean.TRUE);
        return HotDoctorDTOConverter.convert(list);
    }

    @Override
    public List<DoctorDTO> getHospitalDoctor(ProtoDoctorSearchForm form) {
        log.info("ProtoDoctorSearchForm = {}", GsonUtil.toJson(form));
        List<HospitalDoctor> list = doctorRepository.findAll(generateSpecification(form));
        return DoctorDTOConverter.convert(list);
    }


    @Override
    public PageData<DoctorDTO> listHospitalDoctorWithPage(DoctorSearchForm searchForm) {
        PageRequest request = PageRequest.of(PageRequestUtil.getPage(searchForm.getCurrentPage()), PageRequestUtil.getSize(searchForm.getPageSize()));
        ProtoDoctorSearchForm form = ProtoDoctorSearchForm.builder().build();
        BeanUtils.copyProperties(searchForm, form);
        Page<HospitalDoctor> all = doctorRepository.findAll(generateSpecification(form), request);
        PageData<HospitalDoctor> pageData = PageData.formatList(all, PageRequestUtil.getPage(searchForm.getCurrentPage()), PageRequestUtil.getSize(searchForm.getPageSize()));
        PageData<DoctorDTO> result = new PageData<DoctorDTO>();
        result.setList(DoctorDTOConverter.convert(pageData.getList()));
        result.setCurrentPage(pageData.getCurrentPage());
        result.setPageSize(pageData.getPageSize());
        result.setTotalPage(pageData.getTotalPage());
        result.setTotalCount(pageData.getTotalCount());
        return result;
    }

    @Override
    public void resetPassword(DoctorLoginForm form) {
        if (StringUtils.isEmpty(form.getMobile()) || StringUtils.isEmpty(form.getPassword()) || StringUtils.isEmpty(form.getCode())) {
            throw new NormalException(ResultEnums.PARAM_ERROR);
        }
        if (form.getPassword().length() < 8 || form.getPassword().length() > 20) {
            throw new NormalException(ResultEnums.PASSWORD_LENGTH_ERROR);
        }

        HospitalDoctor doctor = doctorRepository.findByMobile(form.getMobile());
        if (doctor == null) {
            throw new NormalException(ResultEnums.NOT_EXIST);
        }
        if (!checkCode(form.getMobile(), form.getCode())) {
            throw new NormalException(ResultEnums.CODE_LOGIN_FAIL);
        }
        doctor.setPassword(LocalStringUtil.encrypt(form.getPassword()));
        doctorRepository.save(doctor);
        removeCode(form.getMobile());

    }

    @Override
    public boolean doctorInfoChange(DoctorDTO doctorDTO) {
        TDMQMessage<DoctorDTO> message = new TDMQMessage<>();
        message.setUuid(doctorDTO.getDoctorId());
        message.setType(MessageType.DOCTOR_INFO_CHANGE);
        message.setData(doctorDTO);
        //TODO 改造成 tdmq
        return false;
    }

    @Override
    public void editDoctorSign(DoctorSignDTO doctorSignDTO) {
        HospitalDoctor doctor = findById(doctorSignDTO.getDoctorId());
        doctor.setSign(doctorSignDTO.getSign());
        doctorRepository.save(doctor);
    }

    @Override
    public DoctorSignDTO viewDoctorSign(String doctorId) {
        HospitalDoctor doctor = findById(doctorId);
        if (StringUtils.isEmpty(doctor.getSign())) {
            doctor.setSign("");
        }
        return DoctorSignDTO.builder()
                .doctorId(doctorId)
                .sign(doctor.getSign())
                .build();
    }

    @Override
    public DoctorHomeOnlineDTO viewHomeDoctor(String doctorId) {
        HospitalDoctor doctor = findById(doctorId);
        DoctorHomeOnlineDTO dto = new DoctorHomeOnlineDTO();
        BeanUtils.copyProperties(doctor, dto);
        dto.setOnlinePrice(hospitalSettingService.viewDoctorOnlinePriceSetting(dto.getDoctorId()));
        List<DoctorConsultationCountDto> list = userFeignClient.doctorConsultationCount(Collections.singletonList(doctorId));
        DoctorConsultationCountDto ret;
        if (list != null && list.size() > 0) {
            ret = list.get(0);
            BeanUtils.copyProperties(ret, dto);
        }
        return dto;
    }

    @Override
    public HospitalDoctor getHospitalDoctorByMobile(String mobile) {
        return doctorRepository.findByMobile(mobile);
    }

    @Override
    public List<DoctorInfoDTO> doctorSearchDoctor(DoctorSearchForm searchForm) {
        List<DoctorInfoDTO> result = new ArrayList<>();
        if (StringUtils.isEmpty(searchForm.getDoctorName()) && StringUtils.isEmpty(searchForm.getMobile())) {
            return result;
        }
        PageRequest pageRequest = PageRequest.of(PageRequestUtil.getPage(searchForm.getCurrentPage()),PageRequestUtil.getSize(searchForm.getPageSize()));
        Page<HospitalDoctor> doctorList =  doctorRepository.findAll(new Specification<HospitalDoctor>() {
            @Override
            public Predicate toPredicate(Root<HospitalDoctor> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
                List<Predicate> predicateList = new ArrayList<>();

                if (!StringUtils.isEmpty(searchForm.getMobile())) {
                    predicateList.add(builder.equal(root.get("mobile"), searchForm.getMobile()));
                }
                if (!StringUtils.isEmpty(searchForm.getDoctorName())) {
                    predicateList.add(builder.like(root.get("doctorName"), "%" + searchForm.getDoctorName() + "%"));
                }

                Predicate[] predicates = new Predicate[predicateList.size()];
                return query.where(predicateList.toArray(predicates)).getRestriction();
            }
        },pageRequest);
        for (HospitalDoctor doctor : doctorList.getContent()) {
            DoctorInfoDTO dto = new DoctorInfoDTO();
            BeanUtils.copyProperties(doctor, dto);
            result.add(dto);
        }

        return result;
    }

    @Override
    public void updateDoctorRemoteInfo(HospitalDoctor doctor) {
        if(doctor == null){
            return ;
        }
        new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    tencentImFeignClient.setProfile(UserProfileForm.builder()
                            .fromAccount(doctor.getTencentAccountId())
                            .hospital(doctor.getHospitalName())
                            .depName(doctor.getDepName())
                            .image(doctor.getHeadImg())
                            .name(doctor.getDoctorName())
                            .officer(doctor.getOfficer())
                            .phone(doctor.getMobile())
                            .client("doctor")
                            .build());
                    log.info("更新远程医生成功 = {}", doctor.getDoctorId());
                } catch (Exception e) {
                    log.info("更新远程医生异常:{}", doctor.getDoctorId());
                    log.info("json = {}", GsonUtil.toJson(doctor));
                    e.printStackTrace();

                }
            }
        }).start();
    }

    private boolean checkCode(String mobile, String checkCode) {
        String code = redisService.get(mobile);
        return checkCode.equals(code);
    }

    /**
     * 删除有效期内的验证码
     */
    private void removeCode(String mobile) {
        redisService.remove(mobile);
    }

    private Specification<HospitalDoctor> generateSpecification(ProtoDoctorSearchForm form) {
        return new Specification<HospitalDoctor>() {
            @Override
            public Predicate toPredicate(Root<HospitalDoctor> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
                List<Predicate> predicateList = new ArrayList<>();
                if (form.getHospitalId() != null && form.getHospitalId() > 0) {
                    predicateList.add(builder.equal(root.get("hospitalId"), form.getHospitalId()));
                }
                if (form.getJobNumList() != null && form.getJobNumList().size() > 0) {
                    CriteriaBuilder.In<String> in = builder.in(root.get("jobNum").as(String.class));
                    for (String s : form.getJobNumList()) {
                        in.value(s);
                    }
                    predicateList.add(in);
                }
                if (form.getDepId() != null && form.getDepId() > 0) {
                    predicateList.add(builder.equal(root.get("depId"), form.getDepId()));
                }
                if (!StringUtils.isEmpty(form.getKeyword())) {
                    Predicate p1 = builder.like(root.get("doctorName"), "%" + form.getKeyword() + "%");
                    Predicate p2 = builder.like(root.get("py"), "%" + form.getKeyword() + "%");
                    Predicate p3 = builder.like(root.get("wb"), "%" + form.getKeyword() + "%");
                    predicateList.add(builder.or(p1, p2, p3));
                }
                if (form.getNeedShow() != null) {
                    predicateList.add(builder.equal(root.get("needShow"), form.getNeedShow()));
                }

                if(form.getGender()!=null){
                    predicateList.add(builder.equal(root.get("gender"), form.getGender()));
                }

                Predicate[] predicates = new Predicate[predicateList.size()];
                return query.where(predicateList.toArray(predicates)).getRestriction();
            }
        };
    }


    @Override
    public DoctorDTO editDoctor(DoctorEditForm doctorEditForm) {
        HospitalDoctor doctor;
        String token = LocalRequestUtil.getToken();
        HospitalLoginInfo hospitalInfo = GsonUtil.fromJson(redisService.get(token), HospitalLoginInfo.class);
        Hospital hospital = hospitalRepository.findById(hospitalInfo.getHospitalId()).orElseThrow(() -> new NormalException(ResultEnums.NOT_EXIST));
        HospitalDepartmentDTO department = departmentService.getDepartment(doctorEditForm.getDepId());

        if (!StringUtils.isEmpty(doctorEditForm.getId())) {
            doctor = findById(doctorEditForm.getId());
            boolean needChangeDep = !doctor.getDepId().equals(doctorEditForm.getDepId());
            LocalObjectUtil.copyNullValue(doctorEditForm, doctor);
            doctor.setHospitalId(hospitalInfo.getHospitalId());
            doctor.setHospitalName(hospital.getName());
            if(needChangeDep){
                HospitalDepartmentDTO childDep = departmentService.getDepartment(doctor.getDepId());
                HospitalDepartmentDTO parentDep = departmentService.getDepartment(childDep.getPid());
                doctor.setDepName(childDep.getName());
                doctor.setDepDetailName(parentDep.getName()+","+childDep.getName());
            }
            doctor = doctorRepository.save(doctor);

        } else {

            if (StringUtils.isEmpty(doctorEditForm.getMobile()) || StringUtils.isEmpty(doctorEditForm.getJobNum())) {
                throw new NormalException(ResultEnums.PARAM_ERROR);
            }

            HospitalDoctor byMobile = doctorRepository.findByMobile(doctorEditForm.getMobile());
            if (byMobile != null) {
                throw new NormalException(ResultEnums.MOBILE_USED_ERROR);
            }
            DoctorImportDTO dto = new DoctorImportDTO();
            LocalObjectUtil.copyNullValue(doctorEditForm, dto);
            dto.setDepCode(department.getDepCode());
            doctor = createNewHospitalDoctor(hospital.getId(), hospital.getName(), dto, null);

            doctor = doctorRepository.save(doctor);
            formatDoctorTencentAccount(doctor);

        }
        this.updateDoctorRemoteInfo(doctor);//修改腾讯IM扩展资料
        return DoctorDTOConverter.convert(doctor);
    }

    private HospitalDoctor createNewHospitalDoctor(Integer hospitalId, String hospitalName, DoctorImportDTO doctorImportDTO, Map<String, HospitalDepartmentDTO> map) {
        HospitalDoctor doctor = new HospitalDoctor();
        BeanUtils.copyProperties(doctorImportDTO, doctor);
        doctor.setDoctorId(LocalStringUtil.getUUID());
        doctor.setHospitalId(hospitalId);
        doctor.setHospitalName(hospitalName);
        doctor.setPassword(LocalStringUtil.encrypt(doctor.getMobile().substring(doctor.getMobile().length() - 6)));
        formatDoctorTencentAccount(doctor);
        log.info("doctor = {}", GsonUtil.toJson(doctor));
        WordBriefInfo wordBriefInfo = baseFeignClient.getWordBriefInfo(doctorImportDTO.getDoctorName());
        doctor.setPy(wordBriefInfo.getPy());
        doctor.setWb(wordBriefInfo.getWb());
        doctor.setEnableStatus(Boolean.TRUE);
        if (map == null) {
            map = getHospitalDepartmentDTOMap(doctor.getHospitalId());
        }
        if (!StringUtils.isEmpty(doctorImportDTO.getDepCode())) {
            HospitalDepartmentDTO departmentDTO = map.get(doctorImportDTO.getDepCode());
            doctor.setDepId(departmentDTO.getId());
            doctor.setDepName(departmentDTO.getName());
            for (String detailKey : map.keySet()) {
                if (map.get(detailKey).getId().equals(departmentDTO.getPid())) {
                    doctor.setDepDetailName(map.get(detailKey).getName() + "," + departmentDTO.getName());
                }
            }
        }
        return doctor;
    }


    @Override
    public DoctorDTO info(String id) {
        HospitalDoctor doctor = findById(id);
        if(StringUtils.isEmpty(doctor.getWxqrcode())){
            try {
                doctor.setWxqrcode(qrcodeService.generateDoctorQrcode(doctor.getHospitalId(),doctor.getDoctorId(),""));
                doctorRepository.save(doctor);
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        DoctorDTO dto = DoctorDTOConverter.convert(doctor);
        HospitalDepartmentDTO department = departmentService.getDepartment(doctor.getDepId());
        dto.setDepIds(Arrays.asList(department.getPid(), department.getId()));
        return dto;
    }

    @Override
    public void resetSelfPassword(ResetDoctorPasswordForm form) {
        HospitalDoctor doctor = findById(form.getId());
        if (!doctor.getPassword().equals(LocalStringUtil.encrypt(form.getOldPassword()))) {
            throw new NormalException(ResultEnums.OLD_PASSWORD_ERROR);
        }
        doctor.setPassword(LocalStringUtil.encrypt(form.getNewPassword()));
        doctorRepository.save(doctor);
    }

    @Override
    public void resetPassword(String doctorId) {
        HospitalDoctor doctor = findById(doctorId);
        doctor.setPassword(LocalStringUtil.encrypt(doctor.getMobile().substring(doctor.getMobile().length() - 6)));
        doctorRepository.save(doctor);
    }

    @Override
    public boolean checkDoctorList(Integer hospitalId, ExcelImportResult<DoctorImportDTO> result) {
        List<String> mobiles = new ArrayList<>();
        //TODO 同一张表格时有相同的数据检查
        Map<String, HospitalDepartmentDTO> departmentDTOMap = getHospitalDepartmentDTOMap(hospitalId);

        //检查dep code
        Iterator<DoctorImportDTO> iterator = result.getList().iterator();
        while (iterator.hasNext()) {
            DoctorImportDTO doctorImportDTO = iterator.next();
            if (doctorImportDTO.getSkip()) {
                continue;
            }
            mobiles.add(doctorImportDTO.getMobile());
            HospitalDepartmentDTO hospitalDepartmentDTO = departmentDTOMap.get(doctorImportDTO.getDepCode());
            if (hospitalDepartmentDTO == null) {
                doctorImportDTO.setErrorMsg("depCode 不存在或者不是二级科室");
                iterator.remove();
                result.getFailList().add(doctorImportDTO);
            }
        }
        //检查 手机号
        List<HospitalDoctor> doctorList = doctorRepository.findAllByMobileIn(mobiles);
        if (!doctorList.isEmpty()) {
            iterator = result.getList().iterator();
            while (iterator.hasNext()) {
                DoctorImportDTO doctorImportDTO = iterator.next();
                if (doctorImportDTO.getSkip()) {
                    continue;
                }
                for (HospitalDoctor doctor : doctorList) {
                    if (doctorImportDTO.getMobile().equals(doctor.getMobile())) {
                        doctorImportDTO.setErrorMsg("该号码已经存在");
                        iterator.remove();
                        result.getFailList().add(doctorImportDTO);
                    }
                }
            }
        }
        return result.getFailList().size() == 0;
    }

    private void formatDoctorTencentAccount(HospitalDoctor doctor) {
        if ("local".equals(prefix)) {
            prefix = "dev";
        }
        doctor.setTencentAccountId(prefix + doctor.getDoctorId());
        try {
            if (StringUtils.isEmpty(doctor.getHeadImg())) {
                doctor.setHeadImg(CommonConstant.DEFAULT_DOCTOR_HEADIMG);
            }
            userFeignClient.createAccount(doctor.getTencentAccountId(), doctor.getDoctorName(), doctor.getHeadImg());
            AddGroupForm form = new AddGroupForm();
            form.setDoctorId(doctor.getDoctorId());
            form.setHospitalId(doctor.getHospitalId());
            form.setType(1);
            userFeignClient.createDefault(form);
            doctor.setTencentAccount(true);
        } catch (Exception e) {
            log.info("userFeignClient 创建腾讯账号失败");
            e.printStackTrace();

        }
    }

    @Override
    public void importDoctorList(Integer hospitalId, List<DoctorImportDTO> list) {

        Map<String, HospitalDepartmentDTO> map = getHospitalDepartmentDTOMap(hospitalId);
        Hospital hospital = hospitalRepository.findById(hospitalId).orElseThrow(() -> new NormalException(ResultEnums.NOT_EXIST));
        for (DoctorImportDTO doctorImportDTO : list) {
            HospitalDoctor doctor = createNewHospitalDoctor(hospitalId, hospital.getName(), doctorImportDTO, map);
            doctor.setNeedShow(Boolean.TRUE);
            doctorRepository.save(doctor);
            this.updateDoctorRemoteInfo(doctor);
        }
    }

    @Override
    public Map<String, HospitalDepartmentDTO> getHospitalDepartmentDTOMap(Integer hospitalId) {

        List<DepartmentListDTO> hospitalDepartmentList = departmentService.getHospitalDepartment(HospitalDepartmentSearchFrom.builder()
                .hospitalId(hospitalId).build());

        Map<String, HospitalDepartmentDTO> result = new HashMap<>();
        for (DepartmentListDTO dto : hospitalDepartmentList) {
            if (!StringUtils.isEmpty(dto.getDepCode())) {
                HospitalDepartmentDTO parent = new HospitalDepartmentDTO();
                parent.setPid(0);
                BeanUtils.copyProperties(dto, parent);
                result.put(dto.getDepCode(), parent);
            }
            for (HospitalDepartmentDTO hospitalDepartmentDTO : dto.getList()) {
                if (!StringUtils.isEmpty(hospitalDepartmentDTO.getDepCode())) {
                    result.put(hospitalDepartmentDTO.getDepCode(), hospitalDepartmentDTO);
                }
            }
        }
        return result;
    }

    @Override
    public List<DoctorHomeOnlineDTO> listHomeExpertDoctor(Integer hospitalId) {
        List<HospitalDoctor> doctorList = doctorRepository.findAllByHospitalIdAndHotStatusAndNeedShowOrderBySorting(hospitalId, true, true);
        List<DoctorHomeOnlineDTO> result = new ArrayList<>();

        for (HospitalDoctor doctor : doctorList) {
            DoctorHomeOnlineDTO dto = new DoctorHomeOnlineDTO();
            BeanUtils.copyProperties(doctor, dto);
            dto.setOnlinePrice(hospitalSettingService.viewDoctorOnlinePriceSetting(dto.getDoctorId()));
            result.add(dto);
        }
        if (result.size() > 0) {
            return formatTreatmentCount(result);
        }
        return result;

    }

    private List<DoctorHomeOnlineDTO> formatTreatmentCount(List<DoctorHomeOnlineDTO> list) {
        List<String> doctorIds = new ArrayList<>();
        for (DoctorHomeOnlineDTO doctor : list) {
            doctorIds.add(doctor.getDoctorId());
        }
        log.info("dddddd");
        List<DoctorConsultationCountDto> countList = userFeignClient.doctorConsultationCount(doctorIds);
        log.info("eeeeeeee");
        Map<String, DoctorConsultationCountDto> map = new HashMap<>();
        for (DoctorConsultationCountDto dto : countList) {
            map.put(dto.getDoctorId(), dto);
        }
        for (DoctorHomeOnlineDTO doctor : list) {
            DoctorConsultationCountDto dto = map.get(doctor.getDoctorId());
            if (dto != null) {
                BeanUtils.copyProperties(dto, doctor);
            }
        }
        log.info("ffffffff");
        return list;
    }


    @Override
    public DoctorLoginInfo login(DoctorLoginForm form) {
        HospitalDoctor doctor = doctorRepository.findByMobile(form.getMobile());
        if (doctor == null || !doctor.getPassword().equals(LocalStringUtil.encrypt(form.getPassword()))) {
            throw new NormalException(ResultEnums.LOGIN_FAIL);
        }
        DoctorLoginInfo loginInfo = translateDoctorToLoginInfoAndSaveToRedis(doctor);
        removeCode(form.getMobile());
        return loginInfo;

    }

    private DoctorLoginInfo translateDoctorToLoginInfoAndSaveToRedis(HospitalDoctor doctor) {
        if (StringUtils.isEmpty(doctor.getHeadImg())) {
            doctor.setHeadImg(CommonConstant.DEFAULT_DOCTOR_HEADIMG);
        }

        DoctorLoginInfo info = new DoctorLoginInfo();
        BeanUtils.copyProperties(doctor, info);
        String token = LocalStringUtil.getUUID();
        info.setToken(token);

        if (!doctor.getTencentAccount()) {//还没有创建腾讯账号，开始创建
            if ("local".equals(prefix)) {
                prefix = "dev";
            }
            doctor.setTencentAccountId(prefix + doctor.getDoctorId());
            info.setTencentAccountId(doctor.getTencentAccountId());
            formatDoctorTencentAccount(doctor);
            doctor.setTencentAccount(true);
            doctorRepository.save(doctor);

        }

        String s = userFeignClient.userSign(doctor.getTencentAccountId());
        if (StringUtils.isEmpty(s)) {
            throw new NormalException(ResultEnums.TENCENT_ACCOUNT_USER_SIGN_ERROR);
        }
        info.setSign(s);
        info.setPrescriptionSign(doctor.getSign());
        redisService.set(token, GsonUtil.toJson(info));
        return info;
    }


    @Override
    public List<DoctorHomeOnlineDTO> listHomeDoctor(HomeSearchDoctorForm form) {
        if (form.getHospitalId() == null || form.getHospitalId() <= 0) {
            throw new NormalException(ResultEnums.PARAM_ERROR);
        }
        Set<String> typeDoctorIds = new HashSet<>();
        Set<String> labelDoctorIds = new HashSet<>();
        Set<String> mergeDoctorIds = null;
        List<DoctorHomeOnlineDTO> result = new ArrayList<>();
        if (form.getType() != null) {
            BanCiSearchForm banCiSearchForm = BanCiSearchForm.builder()
                    .hospitalId(form.getHospitalId())
                    .depId(form.getDepId())
                    .baseTime(LocalDateTime.now())
                    .available(true)
                    .type(BanCiType.online)
                    .build();

            List<HospitalDoctorBanCi> doctorBanCiList = banCiSearchService.searchBanCi(banCiSearchForm);
            for (HospitalDoctorBanCi doctorBanCi : doctorBanCiList) {
                switch (form.getType()) {
                    case pic:
                        if (doctorBanCi.getPic() > doctorBanCi.getPicUsed()) {
                            typeDoctorIds.add(doctorBanCi.getDoctorId());
                        }
                        break;
                    case video:
                        if (doctorBanCi.getVideo() > doctorBanCi.getVideoUsed()) {
                            typeDoctorIds.add(doctorBanCi.getDoctorId());
                        }
                        break;
                    case voice:
                        if (doctorBanCi.getVoice() > doctorBanCi.getVoiceUsed()) {
                            typeDoctorIds.add(doctorBanCi.getDoctorId());
                        }
                    default:
                        break;
                }
            }
            mergeDoctorIds = typeDoctorIds;
        }

        if (form.getLabel() != null) {
            List<HospitalDoctorBindLabel> bindLabelList = bindLabelRepository.findAllByHospitalId(form.getHospitalId());
            for (HospitalDoctorBindLabel label : bindLabelList) {
                Set<String> strSet = LocalStringUtil.splitStrToSet(label.getLabelNames());
                if (strSet.contains(form.getLabel())) {
                    labelDoctorIds.add(label.getDoctorId());
                }
            }
            if (mergeDoctorIds == null) {
                mergeDoctorIds = labelDoctorIds;
            } else {
                mergeDoctorIds.retainAll(labelDoctorIds);//交集
            }
        }
        if (mergeDoctorIds != null && mergeDoctorIds.size() == 0) {
            return result;
        }

        Set<String> finalMergeDoctorIds = mergeDoctorIds;
        List<Sort.Order> orderList = new ArrayList<>();
        if (form.getSortPraise() != null) {
            if (form.getSortPraise() == 0) {
                orderList.add(Sort.Order.asc("praise"));
            } else {
                orderList.add(Sort.Order.desc("praise"));
            }
        }

        if (form.getSortTreatmentCnt() != null) {
            if (form.getSortTreatmentCnt() == 0) {
                orderList.add(Sort.Order.asc("treatmentCnt"));
            } else {
                orderList.add(Sort.Order.desc("treatmentCnt"));
            }
        }
        orderList.add(Sort.Order.desc("hotStatus"));

        List<HospitalDoctor> list = doctorRepository.findAll(new Specification<HospitalDoctor>() {
            @Override
            public Predicate toPredicate(Root<HospitalDoctor> root, CriteriaQuery<?> query, CriteriaBuilder builder) {
                List<Predicate> predicateList = new ArrayList<>();
                predicateList.add(builder.equal(root.get("hospitalId"), form.getHospitalId()));
                if (finalMergeDoctorIds != null && finalMergeDoctorIds.size() > 0) {
                    CriteriaBuilder.In<String> in = builder.in(root.get("doctorId").as(String.class));
                    for (String s : finalMergeDoctorIds) {
                        in.value(s);
                    }
                    predicateList.add(in);
                }
                log.info("========= {}",GsonUtil.toJson(form));
                if (StringUtils.hasText(form.getDoctorName())) {
                    log.info("aaaaaaaaa");
                    Predicate doctorNameLike = builder.like(root.get("doctorName"), "%" + form.getDoctorName() + "%");
                    Predicate needShowTure = builder.equal(root.get("needShow"), Boolean.TRUE);
                    Predicate p1 = builder.and(doctorNameLike, needShowTure);

                    Predicate doctorNameEqual = builder.equal(root.get("doctorName"), form.getDoctorName());
                    Predicate needShowFalse = builder.equal(root.get("needShow"), Boolean.FALSE);
                    Predicate p2 = builder.and(doctorNameEqual, needShowFalse);

                    predicateList.add(builder.or(p1, p2));
                } else {
                    log.info("bbbbbbbb");
                    predicateList.add(builder.equal(root.get("needShow"), Boolean.TRUE));
                }
                if (form.getDepId() != null && form.getDepId() > 0) {
                    predicateList.add(builder.equal(root.get("depId"), form.getDepId()));
                }
                if (!StringUtils.isEmpty(form.getOfficer())) {
                    predicateList.add(builder.equal(root.get("officer"), form.getOfficer()));
                }
                Predicate[] predicates = new Predicate[predicateList.size()];
                return query.where(predicateList.toArray(predicates)).getRestriction();
            }
        }, Sort.by(orderList));
        log.info("list = {}", GsonUtil.toJson(list));
        for (HospitalDoctor doctor : list) {
            DoctorHomeOnlineDTO dto = new DoctorHomeOnlineDTO();
            BeanUtils.copyProperties(doctor, dto);
            dto.setOnlinePrice(hospitalSettingService.viewDoctorOnlinePriceSetting(dto.getDoctorId()));
            result.add(dto);
        }
        if (result.size() > 0) {
            return formatTreatmentCount(result);
        }
        log.info("cccccc");
        return result;
    }

    @Override
    public DoctorLoginInfo loginWithCode(DoctorLoginForm form) {
        if (StringUtils.isEmpty(form.getMobile()) || StringUtils.isEmpty(form.getCode())) {
            throw new NormalException(ResultEnums.PARAM_ERROR);
        }

        if (!checkCode(form.getMobile(), form.getCode())) {
            throw new NormalException(ResultEnums.CODE_LOGIN_FAIL);
        }

        HospitalDoctor doctor = doctorRepository.findByMobile(form.getMobile());
        if (doctor == null) {
            throw new NormalException(ResultEnums.NOT_EXIST);
        }
        return translateDoctorToLoginInfoAndSaveToRedis(doctor);
    }


    private HospitalDoctor findById(String doctorId) {
        return doctorRepository.findById(doctorId).orElseThrow(() -> new NormalException(ResultEnums.NOT_EXIST));
    }

    @Value("${spring.profiles.active}")
    private String prefix;

    private UserFeignClient userFeignClient;

    private HospitalDoctorRepository doctorRepository;

    private DepartmentService departmentService;

    private BaseFeignClient baseFeignClient;

    private HospitalRepository hospitalRepository;

    private HospitalSettingService hospitalSettingService;

    private RedisService redisService;

    private BanCiSearchService banCiSearchService;

    private HospitalDoctorBindLabelRepository bindLabelRepository;

    private TencentImFeignClient tencentImFeignClient;

    private QrcodeService qrcodeService;

    @Autowired
    public void setDoctorRepository(HospitalDoctorRepository doctorRepository) {
        this.doctorRepository = doctorRepository;
    }

    @Autowired
    public void setDepartmentService(DepartmentService departmentService) {
        this.departmentService = departmentService;
    }

    @Autowired
    public void setBaseFeignClient(BaseFeignClient baseFeignClient) {
        this.baseFeignClient = baseFeignClient;
    }

    @Autowired
    public void setHospitalRepository(HospitalRepository hospitalRepository) {
        this.hospitalRepository = hospitalRepository;
    }

    @Autowired
    public void setHospitalSettingService(HospitalSettingService hospitalSettingService) {
        this.hospitalSettingService = hospitalSettingService;
    }

    @Autowired
    public void setRedisService(RedisService redisService) {
        this.redisService = redisService;
    }

    @Autowired
    public void setBanCiSearchService(BanCiSearchService banCiSearchService) {
        this.banCiSearchService = banCiSearchService;
    }

    @Autowired
    public void setBindLabelRepository(HospitalDoctorBindLabelRepository bindLabelRepository) {
        this.bindLabelRepository = bindLabelRepository;
    }

    @Autowired
    public void setUserFeignClient(UserFeignClient userFeignClient) {
        this.userFeignClient = userFeignClient;
    }

    @Autowired
    public void setTencentImFeignClient(TencentImFeignClient tencentImFeignClient) {
        this.tencentImFeignClient = tencentImFeignClient;
    }
    @Autowired
    public void setQrcodeService(QrcodeService qrcodeService) {
        this.qrcodeService = qrcodeService;
    }
}
